#include "stdio.h"
#include "stdlib.h"

#define N 5
#define M 3

// 可利用资源数组
int Available[M];
// 最大资源数组
int Max[N][M];
// 已经分配资源数组
int Allocation[N][M];
// 需求数组
int Need[N][M];
// 是否完成
int Success[N];

/**
 * 读取一维数组
*/
void read1_data(char *fileName, int arr[], int m)
{
    int i;
    FILE *fp = fopen(fileName, "rb");
    for (i = 0; i < m; i++)
    {
        fscanf(fp, "%d", &arr[i]);
    }
}

void display() 
{
    printf("可利用资源数组： ");
    for (int i = 0; i < M; i++)
    {
        printf("%d ", Available[i]);
    }
    printf("\n\n");
    printf("当前系统资源情况表：\n");
    printf("PID       Max      Allocation    Need     Success\n");
    for (int i = 0; i < N; i++)
    {
        printf("P%d    ", i);
        for (int j = 0; j < M; j++)
        {
            printf("%3d", Max[i][j]);
        }
        printf("   ");
        for (int j = 0; j < M; j++)
        {
            printf("%3d", Allocation[i][j]);
        }
        printf("   ");
        for (int j = 0; j < M; j++)
        {
            printf("%3d", Need[i][j]);
        }
        printf("   %3d", Success[i]);
        printf("\n");
    }

}

/**
 * 读取二维数组
*/
void read2_data(char *fileName, int arr[][M], int n, int m)
{
    int i;
    int j;
    FILE *fp = fopen(fileName, "rb");
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < m; j++)
        {
            fscanf(fp, "%d", &arr[i][j]);
        }
    }
}

void init()
{
    read1_data("Available.txt", Available, M);
    read2_data("Max.txt", Max, N, M);
    read2_data("Allocation.txt", Allocation, N, M);
    // 设置Need
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; j++)
        {
            Need[i][j] = Max[i][j] - Allocation[i][j];
        }
    }
    // 重新设置Available
    for (int i = 0; i < M; i++)
    {
        int sum = 0;
        for (int j = 0; j < N; j++)
        {
            sum += Allocation[j][i];
        }
        Available[i] -= sum;
    }
}

/**
 * 安全检查
*/
int check_secure()
{
    // 工作向量
    int work[M];
    // 完成向量
    int finish[N];
    // work一开始等于Available, finish全部置0
    for (int i = 0; i < M; i++)
    {
        work[i] = Available[i];
    }
    for (int i = 0; i < N; i++)
    {
        finish[i] = 0;
    }
    printf("安全序列： ");
    while (1)
    {
        // 标识这一轮是否有进程完成
        int flag = 0;
        for (int i = 0; i < N; i++)
        {
            // 如果这个进程没有完成，则判断其是否可以完成
            if (!finish[i])
            {
                // temp=0表示可以完成
                int temp = 0;
                for (int j = 0; j < M; j++)
                {
                    if (Need[i][j] > work[j])
                    {
                        temp = 1;
                        break;
                    }
                }
                if (!temp)
                {
                    for (int j = 0; j < M; j++)
                    {
                        work[j] += Allocation[i][j];
                    }
                    finish[i] = 1;
                    flag++;
                    printf("%d ", i);
                }
            }
        }
        if (!flag)
        {
            break;
        }
    }
    printf("\n");
    for (int i = 0; i < N; i++)
    {
        if (!finish[i])
        {
            // 有不能完成的则为不安全
            return 0;
        }
    }
    // 安全返回1
    return 1;
}

void handle(int current, int request[])
{
    // 进程任务是否完成
    int finish = 1;
    for (int i = 0; i < M; i++)
    {
        if (request[i] > Need[current][i])
        {
            printf("请求的资源大于需要的资源\n");
            return;
        }
        if (request[i] > Available[i])
        {
            printf("没有足够的资源可分配\n");
            return;
        }
    }
    for (int i = 0; i < M; i++)
    {
        Available[i] -= request[i];
        Allocation[current][i] += request[i];
        Need[current][i] -= request[i];
    }
    // 安全检查
    if (!check_secure())
    {
        //如果检查不通过 回撤改变
        for (int i = 0; i < M; i++)
        {
            Available[i] += request[i];
            Allocation[current][i] -= request[i];
            Need[current][i] += request[i];
        }
        printf("安全检查未通过\n");
        return;
    }
    for (int i = 0; i < M; i++)
    {
        if (Need[current][i] > 0)
        {
            finish = 0;
            break;
        }
    }
    // 如果进程need都为0表示进程完成，回收资源
    if (finish)
    {
        for (int i = 0; i < M; i++)
        {
            Available[i] += Allocation[current][i];
        }
        Success[current] = 1;
    }
}

// 暂停
void pause()
{
    getchar();
    printf("按任意键继续");
    getchar();
}

int main()
{
    // 当前线程请求资源数组
    int request[M];
    // 当前线程id
    int current;
    init();
    check_secure();
    while (1)
    {
        display();
        printf("输入要分配的进程\n");
        scanf("%d", &current);
        for (int i = 0; i < M; i++)
        {
            printf("输入要分配的资源%d数量\n", i);
            scanf("%d", &request[i]);
        }
        handle(current, request);
        pause();
    }
    return 0;
}